From ae22476931519c8f3846a3995da77b53ef90e38c Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 29 Mar 2011 00:59:49 +0200 Subject: [PATCH] theming: Implement non-uniform border-width in the theming engine. The border-width CSS parameter takes up to 4 values, but it was being ignored by the theming engine until now. --- gtk/gtkthemingengine.c | 155 +++++++++++++++++++++++++++++++---------- 1 file changed, 119 insertions(+), 36 deletions(-) diff --git a/gtk/gtkthemingengine.c b/gtk/gtkthemingengine.c index a207b32f52..10bb949ca7 100644 --- a/gtk/gtkthemingengine.c +++ b/gtk/gtkthemingengine.c @@ -1455,6 +1455,32 @@ _cairo_round_rectangle_sides (cairo_t *cr, } } +static void +_cairo_uneven_frame (cairo_t *cr, + gdouble radius, + gdouble x, + gdouble y, + gdouble width, + gdouble height, + GtkBorder *border, + GtkJunctionSides junction) +{ + cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); + cairo_set_line_width (cr, 1); + + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x, y, + width, height, + SIDE_ALL, junction); + + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x + border->left, + y + border->top, + width - border->left - border->right, + height - border->top - border->bottom, + SIDE_ALL, junction); +} + /* Set the appropriate matrix for * patterns coming from the style context */ @@ -1836,6 +1862,7 @@ render_frame_internal (GtkThemingEngine *engine, gdouble progress, d1, d2, m; gboolean running; GtkBorder border; + gboolean uniform_border; state = gtk_theming_engine_get_state (engine); @@ -1850,6 +1877,9 @@ render_frame_internal (GtkThemingEngine *engine, running = gtk_theming_engine_state_is_running (engine, GTK_STATE_PRELIGHT, &progress); border_width = MIN (MIN (border.top, border.bottom), MIN (border.left, border.right)); + uniform_border = (border.top == border.bottom && + border.top == border.left && + border.top == border.right); if (running) { @@ -1884,28 +1914,41 @@ render_frame_internal (GtkThemingEngine *engine, cairo_set_line_width (cr, border_width); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); - if (border_width > 1) + gdk_cairo_set_source_rgba (cr, &border_color); + + if (uniform_border) { - x += (gdouble) border_width / 2; - y += (gdouble) border_width / 2; - width -= border_width; - height -= border_width; + if (border_width > 1) + { + x += (gdouble) border_width / 2; + y += (gdouble) border_width / 2; + width -= border_width; + height -= border_width; + } + else if (border_width == 1) + { + x += 0.5; + y += 0.5; + width -= 1; + height -= 1; + } + + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x, y, width, height, + SIDE_ALL & ~(hidden_side), + junction); + cairo_stroke (cr); } - else if (border_width == 1) + else { - x += 0.5; - y += 0.5; - width -= 1; - height -= 1; + cairo_save (cr); + _cairo_uneven_frame (cr, (gdouble) radius, + x, y, width, height, + &border, junction); + cairo_fill (cr); + cairo_restore (cr); } - _cairo_round_rectangle_sides (cr, (gdouble) radius, - x, y, width, height, - SIDE_ALL & ~(hidden_side), - junction); - gdk_cairo_set_source_rgba (cr, &border_color); - cairo_stroke (cr); - break; case GTK_BORDER_STYLE_INSET: case GTK_BORDER_STYLE_OUTSET: @@ -1932,29 +1975,69 @@ render_frame_internal (GtkThemingEngine *engine, m = MIN (width, height); m /= 2; - if (border_style == GTK_BORDER_STYLE_INSET) - gdk_cairo_set_source_rgba (cr, &lighter); - else - gdk_cairo_set_source_rgba (cr, &border_color); + if (uniform_border) + { + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_rgba (cr, &lighter); + else + gdk_cairo_set_source_rgba (cr, &border_color); - _cairo_round_rectangle_sides (cr, (gdouble) radius, - x + d1, y + d1, - width - d2, height - d2, - (SIDE_BOTTOM | SIDE_RIGHT) & ~(hidden_side), - junction); - cairo_stroke (cr); + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x + d1, y + d1, + width - d2, height - d2, + (SIDE_BOTTOM | SIDE_RIGHT) & ~(hidden_side), + junction); + cairo_stroke (cr); + + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_rgba (cr, &border_color); + else + gdk_cairo_set_source_rgba (cr, &lighter); - if (border_style == GTK_BORDER_STYLE_INSET) - gdk_cairo_set_source_rgba (cr, &border_color); + _cairo_round_rectangle_sides (cr, (gdouble) radius, + x + d1, y + d1, + width - d2, height - d2, + (SIDE_TOP | SIDE_LEFT) & ~(hidden_side), + junction); + cairo_stroke (cr); + } else - gdk_cairo_set_source_rgba (cr, &lighter); + { + cairo_save (cr); - _cairo_round_rectangle_sides (cr, (gdouble) radius, - x + d1, y + d1, - width - d2, height - d2, - (SIDE_TOP | SIDE_LEFT) & ~(hidden_side), - junction); - cairo_stroke (cr); + /* Bottom/right */ + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_rgba (cr, &lighter); + else + gdk_cairo_set_source_rgba (cr, &border_color); + + _cairo_uneven_frame (cr, (gdouble) radius, + x, y, width, height, + &border, junction); + cairo_fill (cr); + + /* Top/left */ + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + width, y); + cairo_line_to (cr, x + width - border.right - radius / 2, y + border.top + radius / 2); + cairo_line_to (cr, x + width - border.right - radius / 2, y + height - border.bottom - radius / 2); + cairo_line_to (cr, x + border.left + radius / 2, y + height - border.bottom - radius / 2); + cairo_line_to (cr, x, y + height); + cairo_close_path (cr); + + cairo_clip (cr); + + if (border_style == GTK_BORDER_STYLE_INSET) + gdk_cairo_set_source_rgba (cr, &border_color); + else + gdk_cairo_set_source_rgba (cr, &lighter); + + _cairo_uneven_frame (cr, (gdouble) radius, + x, y, width, height, + &border, junction); + cairo_fill (cr); + cairo_restore (cr); + } if (border_width > 1) { -- 2.30.2